#include "ModuleVJObjectDetection.h"

void ModuleVJObjectDetection::init(QCVModuleHandlerInterface * parent)
{
	this->parent=parent;
	win=new QWidget();
  layout=new QGridLayout(win);
	pb_browse=new QPushButton("...",win);
	pb_browse->setFixedWidth(30);
	l_classifierFile=new QLabel("Classifieur",win);	
	l_scale=new QLabel("Facteur de redimmentionnement",win);
	l_scaleStep=new QLabel("Pas d'echelle",win);
	l_neighbors=new QLabel("Nombre de voisins",win);
	l_minSize=new QLabel("Taille minimale",win);

	sb_scale=new QDoubleSpinBox(win);
	sb_scale->setValue(1.0);
	sb_scale->setRange(1.0,10.0);
	le_classifierFile=new QLineEdit(win);

	sb_scaleStep=new QSpinBox(win);
	sb_scaleStep->setSuffix("%");
	sb_scaleStep->setRange(0,100);
	sb_scaleStep->setValue(10);

	sb_neighbors=new QSpinBox(win);
	sb_neighbors->setRange(0,100);
	sb_neighbors->setValue(2);

	sb_minSizeX=new QSpinBox(win);
	sb_minSizeX->setRange(0,100);
	sb_minSizeX->setValue(10);
	sb_minSizeX->setPrefix("w=");
	sb_minSizeY=new QSpinBox(win);
	sb_minSizeY->setRange(0,100);
	sb_minSizeY->setValue(10);
	sb_minSizeY->setPrefix("h=");

	layout->addWidget(l_classifierFile,0,0);
	layout->addWidget(le_classifierFile,0,1);
	layout->addWidget(pb_browse,0,2);
	layout->addWidget(l_scale,1,0);
	layout->addWidget(sb_scale,1,1);
	layout->addWidget(l_scaleStep,2,0);
	layout->addWidget(sb_scaleStep,2,1);
	layout->addWidget(l_neighbors,3,0);
	layout->addWidget(sb_neighbors,3,1);
	layout->addWidget(l_minSize,4,0);
	layout->addWidget(sb_minSizeX,4,1);
	layout->addWidget(sb_minSizeY,4,2);

	connect(pb_browse,SIGNAL(clicked()),this,SLOT(s_browse()));
	
}
////////////////////////////////////////////////////////////////////////////////
void ModuleVJObjectDetection::free()
{
	delete win;
}
////////////////////////////////////////////////////////////////////////////////
cv::Mat & ModuleVJObjectDetection::process()
{
	if(!cascade.empty())
	{
		//Conversion en niveau de gris puis redimentionnement de l'image courante		
		cv::Mat gray, smallImg( cvRound (currentFrame.rows/sb_scale->value()), cvRound(currentFrame.cols/sb_scale->value()), CV_8UC1 );
    cv::cvtColor( currentFrame, gray, CV_BGR2GRAY );
    cv::resize( gray, smallImg, smallImg.size(), 0, 0, cv::INTER_LINEAR );
    cv::equalizeHist( smallImg, smallImg );

		//detection multi echelle des objets
		std::vector<cv::Rect> faces;
		cascade.detectMultiScale( smallImg, faces,
		  1+sb_scaleStep->value()/100.0, //on reduit de 10% a chaque etapes 
			sb_neighbors->value(),   //Nombre minimum de voisins
			0
		  //|CV_HAAR_FIND_BIGGEST_OBJECT
		  //|CV_HAAR_DO_ROUGH_SEARCH
		  |CV_HAAR_SCALE_IMAGE
		  ,
		  cv::Size(sb_minSizeX->value(), sb_minSizeY->value()) );//Taille Minimum
	
		//recuperation et conversion des boxes en matrice
		boxes.create(faces.size(),5);
		boxes.setTo(0);
		int i=0;
		for( std::vector<cv::Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
    {
			boxes(i,0)=r->x*sb_scale->value();
			boxes(i,1)=r->y*sb_scale->value();
			boxes(i,2)=(r->x+r->width)*sb_scale->value();
			boxes(i,3)=(r->y+r->height)*sb_scale->value();
			boxes(i,4)=i;
		}

	}
	return boxes;
}
////////////////////////////////////////////////////////////////////////////////
void ModuleVJObjectDetection::setInput(int n,const cv::Mat & m)
{
	if(n==0)
	{	
		currentFrame=m.clone();
	}
}
////////////////////////////////////////////////////////////////////////////////
QWidget* ModuleVJObjectDetection::widget()
{
	return win;
}
////////////////////////////////////////////////////////////////////////////////
QString ModuleVJObjectDetection::getName()
{
	return trUtf8("Détecteur d'objets de Viola-Jones");
}
////////////////////////////////////////////////////////////////////////////////
int ModuleVJObjectDetection::nbInputs()
{
	return 1;
}
////////////////////////////////////////////////////////////////////////////////
bool ModuleVJObjectDetection::setParams(QString params)
{
	QStringList list_params=params.split(";");
		
	if(list_params.size()==6)
	{
		le_classifierFile->setText(list_params[0]);
		sb_scale->setValue(list_params[1].toFloat());
		sb_scaleStep->setValue(list_params[2].toInt());
		sb_neighbors->setValue(list_params[3].toInt());
		sb_minSizeX->setValue(list_params[4].toInt());
		sb_minSizeY->setValue(list_params[5].toInt());

		if( !cascade.load(le_classifierFile->text().toAscii().data()) )
    {
			le_classifierFile->setText("Erreur");
		}
		return true;
	}
	else
	{
		return false;
	}	
}
////////////////////////////////////////////////////////////////////////////////
QCVModuleInterface * ModuleVJObjectDetection::clone()
{
	return new ModuleVJObjectDetection;
}
////////////////////////////////////////////////////////////////////////////////
QString ModuleVJObjectDetection::getParams()
{
	return le_classifierFile->text()+tr(";")+
				 QString::number(sb_scale->value())+tr(";")+
				 QString::number(sb_scaleStep->value())+tr(";")+
				 QString::number(sb_neighbors->value())+tr(";")+
				 QString::number(sb_minSizeX->value())+tr(";")+
				 QString::number(sb_minSizeY->value());
}
////////////////////////////////////////////////////////////////////////////////
QString ModuleVJObjectDetection::help(int id)
{
	if(id==-2)
	{
		return trUtf8("Détecte des objets via la methode de Viola et Jones");
	}
	else if(id==-1)
	{
		return tr("boxes");
	}
	else if(id==0)
	{
		return tr("image");
	}
	else
	{
		return tr("erreur");
	}
}
////////////////////////////////////////////////////////////////////////////////
void ModuleVJObjectDetection::s_browse()
{
	QString fn=QFileDialog::getOpenFileName(NULL,"Ouvrir un classifieur en cascade","haarcascades",tr("*.xml"));
	
	if(!fn.isEmpty())
	{
		if( !cascade.load(fn.toAscii().data()) )
    {
			le_classifierFile->setText("Erreur");
		}
		else
		{
			le_classifierFile->setText(fn);
		}
	}
}
////////////////////////////////////////////////////////////////////////////////
Q_EXPORT_PLUGIN2(ModuleVJObjectDetection_plugin,ModuleVJObjectDetection);  
